<template>
	<div class="container">
		<div class="chat-box">
			<div class="user-list" :style="[!state.isRetract ? 'width:0' : '']">
				<div
					class="user-item"
					v-for="(item, index) in state.chatUserList"
					:class="{ active: index === state.currentUserIdx }"
					:key="item.UserID"
					@click="clickUserChat(item, index)"
				>
					<el-image :src="userFill" />
					<div class="info">
						<div class="title">{{ item.UserID }}</div>
						<div class="the-latest-word">{{ item.Msg }}</div>
					</div>
					<div class="other">
						<span class="the-latest-word-time">{{ item.time }}</span>
						<div class="unread-num" v-if="item.status === ENewestInfoStatus.unread"></div>
					</div>
					<div></div>
				</div>
			</div>
			<div class="left" v-if="state.currentUserIdx !== null">
				<div class="head">
					<div class="retract-right" @click="state.isRetract = !state.isRetract">
						<SvgIcon v-if="state.isRetract" name="ele-Expand" :size="22" color="var(--el-color-primary)" />
						<SvgIcon v-else name="ele-Fold" :size="22" color="var(--el-color-primary)" />
					</div>
					<div class="title-left">{{ state.userInfo.UserID }}</div>
				</div>
				<ChatContent
					:chatting-record-list="state.chattingRecordList"
					@sendMessageReq="sendMessageReq"
					@fileSendMessage="fileSendMessage"
					:identity="EIdentity.CustomerService"
					v-model:content="state.content"
				/>
			</div>
			<div class="left" v-else style="display: flex; justify-content: center">
				<img src="../../../assets/icon/Chat.svg" alt="" style="width: 105px" />
			</div>
		</div>
	</div>
</template>
<script lang="ts" setup>
import { ws } from '/@/utils/websocket';
import { Fold } from '@element-plus/icons-vue';
import { ClickOutside as vClickOutside, ElMessage } from 'element-plus';
import Upload from '/@/components/Linxyun/FileClient/index.vue';
import ChatContent from './cpn/chatContent.vue';
import { Base64 } from '/@/utils/b64';
import { httpReqeustApi } from '/@/api/linxyun/base/index.ts';
import { formatDate, formatPast } from '/@/utils/formatTime';
import { sizeTostr, handleFileDown } from '/@/utils/extendMethods';
import { useUserInfo } from '/@/stores/userInfo';
import textImgIcon from '/@/assets/icon/file-icon-text.png';
import defaultImgIcon from '/@/assets/icon/file-icon-default.png';
import imgIcon from '/@/assets/icon/file-icon-img.png';
import userFill from '/@/assets/icon/userFill.svg';
import { EMsgType, EIdentity, IChattingRecord } from './type';
enum ENewestInfoStatus {
	read,
	unread,
}
interface IState {
	serveType: number | null;
	Recver: string;
	chatUserID: string; // 用户ID
	msgTypes: EMsgType;
	uploadUrl: string;
	content: string;
	fileUrlPrefix: string;
	chattingRecordList: IChattingRecord[];
	self: Record<string, any>;
	isRetract: boolean;
	fileIcon: string;
	fileInfo: Record<string, any>;
	chatUserList: Record<string, any>[];
	allUserChattingRecordList: Record<string, Array<IChattingRecord>>;
	userInfo: Record<string, any>;
	currentUserIdx: number | null;
}

const httpRequest = httpReqeustApi();
const userInfoStore = useUserInfo();
const state = reactive<IState>({
	serveType: null,
	Recver: '',
	chatUserID: '',
	msgTypes: EMsgType.text,
	uploadUrl: '',
	content: '',
	fileUrlPrefix: '',
	chattingRecordList: [], // 聊天记录
	self: {},
	isRetract: true,
	fileIcon: defaultImgIcon,
	fileInfo: {},
	chatUserList: [],
	allUserChattingRecordList: {},
	userInfo: {},
	currentUserIdx: null,
});
// 发送消息
const sendMessageReq = () => {
	console.log('sendMessageReq', { msgTypes: state.msgTypes, content: state.content });
	if ((state.msgTypes === EMsgType.text && !state.content) || (state.msgTypes !== EMsgType.text && !state.uploadUrl)) {
		return;
	}
	let content: any = '';

	const newestInfo: Record<string, any> = {
		UserID: state.userInfo.UserID,
		time: formatDate(new Date(), 'HH:MM'),
		Msg: '',
		status: ENewestInfoStatus.read,
	};
	console.log('sendMessageReq', state.content);
	const params: Record<string, any> = {};
	params.Recver = state.userInfo.UserID;
	params.Sender = state.chatUserID;
	params.optype = 'req';
	// params.to_key = BASE_API.ENT_CODE + '#000';
	params.to_key = BASE_API.ENT_CODE;
	params.to_subkey = state.userInfo.UserID;
	// value == 1 发送图片消息
	if (state.msgTypes === EMsgType.img) {
		params.ContentType = EMsgType.img;
		params.Message = state.uploadUrl;
		content = state.uploadUrl;

		newestInfo.Msg = '[图片]';
	} else if (state.msgTypes === EMsgType.text) {
		// 发送普通文字消息
		params.Message = Base64.encode(state.content);
		params.ContentType = EMsgType.text;
		content = state.content;

		newestInfo.Msg = state.content;
	} else if (state.msgTypes === EMsgType.file) {
		// 发送文件
		params.ContentType = EMsgType.file;
		params.Message = {
			link: state.uploadUrl,
			title: state.fileInfo.name,
			size: sizeTostr(state.fileInfo.size),
			status: '已上传',
		};
		const arr = state.uploadUrl.split('.');
		if (arr.length) {
			if (arr[arr.length - 1] === 'txt') {
				state.fileIcon = textImgIcon;
			} else if (['png', 'jpg'].includes(arr[arr.length - 1])) {
				state.fileIcon = imgIcon;
			} else {
				state.fileIcon = defaultImgIcon;
			}
		}
		params.Message.icon = state.fileIcon;
		content = params.Message;

		newestInfo.Msg = '[文件]';
	}
	if (state.userInfo.isWechat) {
		newestInfo.isWechat = true;
		newestInfo.WechatId = state.userInfo.WechatId;
		const Recver = state.userInfo.UserID;
		const params2 = {
			Sender: BASE_API.ENT_CODE + '-' + state.chatUserID,
			MsgType: '0',
			ContentType: params.ContentType,
			Message: params.Message,
			Extend: '',
			MsgClassify: '0',
			Recver: Recver,
			WechatId: state.userInfo.WechatId,
		};
		httpRequest.Get('send_wechat_msg_py', params2);
	} else {
		ws.send(params);
	}

	// 本地保存聊天记录
	const chattingRecord: IChattingRecord = {
		name: '我',
		time: formatDate(new Date(), 'YYYY-mm-dd HH:MM:SS'),
		content: content,
		identity: EIdentity.CustomerService,
		ContentType: params.ContentType,
	};
	saveChattingRecord(chattingRecord, params.Recver);

	saveNewestUserInfo(newestInfo);
	state.content = '';
	state.uploadUrl = '';
	nextTick(() => {
		scrollToBottom();
	});
	return;
};

// 保存聊天记录
const saveChattingRecord = (chattingRecord: IChattingRecord, UserID: string) => {
	if (state.userInfo.UserID) {
		state.chattingRecordList.push(chattingRecord);
		state.allUserChattingRecordList[UserID] = state.chattingRecordList;
	} else {
		const chattingRecordList = state.allUserChattingRecordList[UserID] || [];
		chattingRecordList.push(chattingRecord);
		state.allUserChattingRecordList[UserID] = chattingRecordList;
	}

	const prefix = BASE_API.PROJECT_URI.slice(1);
	localStorage.setItem(prefix + '_allUserChattingRecordList', JSON.stringify(state.allUserChattingRecordList));
	console.log('saveChattingRecord', state.allUserChattingRecordList);
};

const fileSendMessage = (obj: { msgTypes: EMsgType; uploadUrl: string; fileInfo: Record<string, any>[] }) => {
	state.msgTypes = obj.msgTypes;
	state.uploadUrl = obj.uploadUrl;
	state.fileInfo = obj.fileInfo;
	console.log('fileSendMessage', state.msgTypes, state.uploadUrl);
	sendMessageReq();
};

/**
 * 保持最新用户信息
 */
const saveNewestUserInfo = (userInfo: Record<string, any>) => {
	// state.userInfo = userInfo;
	const index = state.chatUserList.findIndex((item) => {
		return userInfo.UserID === item.UserID;
	});
	if (index !== -1) {
		// 如果接受的消息是当前窗口就直接已读
		if (state.currentUserIdx === index) {
			userInfo.status = ENewestInfoStatus.read;
		}
		state.chatUserList[index] = userInfo;
	} else {
		state.chatUserList.push(userInfo);
	}
	console.log('chatUserList', state.chatUserList, index, userInfo);
	const prefix = BASE_API.PROJECT_URI.slice(1);
	localStorage.setItem(prefix + '_chatUserList', JSON.stringify(state.chatUserList));
};
/**
 * 获取本地存储的用户列表
 */
const getChatUserList = () => {
	const prefix = BASE_API.PROJECT_URI.slice(1);
	const chatUserList = localStorage.getItem(prefix + '_chatUserList');
	console.log('getChatUserList', prefix + '_chatUserList', chatUserList);
	if (chatUserList) {
		state.chatUserList = JSON.parse(chatUserList);
	} else {
		// state.chatUserList = [{ UserID: '38-o2GX35FSa8b7P4ntUlkXQx4CE3QU' }];
	}
};

/**
 * 获取所有聊天信息
 */
const getUserChatContent = () => {
	const prefix = BASE_API.PROJECT_URI.slice(1);
	const allUserChattingRecordList = localStorage.getItem(prefix + '_allUserChattingRecordList');
	if (allUserChattingRecordList) {
		state.allUserChattingRecordList = JSON.parse(allUserChattingRecordList);
	}
};

/**
 * 点击用户列表的用户时触发
 */
const clickUserChat = (userInfo: Record<string, any>, index: number) => {
	state.currentUserIdx = index;
	state.userInfo = userInfo;
	state.userInfo.status = ENewestInfoStatus.read;
	for (let index = 0; index < state.chatUserList.length; index++) {
		const tmpUserInfo = state.chatUserList[index];
		if (tmpUserInfo.UserID === userInfo.UserID) {
			tmpUserInfo.status = ENewestInfoStatus.read;
			break;
		}
	}
	const prefix = BASE_API.PROJECT_URI.slice(1);
	localStorage.setItem(prefix + '_chatUserList', JSON.stringify(state.chatUserList));
	state.chattingRecordList = state.allUserChattingRecordList[userInfo.UserID] || [];
	nextTick(() => {
		scrollToBottom();
	});
};
// 初始化
(() => {
	// 如果本地有UserID就直接取,没有就生成UserID
	state.chatUserID = userInfoStore.userInfos?.UserID || '';
	getChatUserList();
	getUserChatContent();
	ws.connect(state.chatUserID);
	ws.onOpen(state.chatUserID);

	let Sender = '';
	ws.recvData(async (onMessage) => {
		const res: Record<string, any> = JSON.parse(onMessage.data);
		console.log('监听WebSocket接受到服务器的消息事件。服务器返回的消息', res);
		if (res.Sender && res.Recver) {
			Sender = res.Sender;
			let content = '';
			const newestInfo = {
				UserID: res.Sender,
				time: formatDate(new Date(), 'HH:MM'),
				Msg: '',
				status: ENewestInfoStatus.unread,
			};
			if (res.optype === 'req') {
				if (res.Message && res.ContentType === EMsgType.text) {
					// 本地保存聊天记录
					content = Base64.decode(res.Message) || '';
					newestInfo.Msg = content;
				} else if (res.Message && [EMsgType.img, EMsgType.file].includes(res.ContentType)) {
					content = res.Message;
					newestInfo.Msg = res.ContentType === EMsgType.img ? '[图片]' : '[文件]';
				}
				const chattingRecord: IChattingRecord = {
					name: '游客',
					time: formatDate(new Date(), 'YYYY-mm-dd HH:MM:SS'),
					content: content,
					identity: EIdentity.Customer,
					ContentType: res.ContentType,
				};
				saveChattingRecord(chattingRecord, res.Sender);
			} else {
				newestInfo.Msg = '';
			}

			saveNewestUserInfo(newestInfo);
		} else if (res.optype === 'ind') {
			const params: Record<string, any> = { SessionID: res.SessionID, current: 1, limit: 1 };
			// 查看本地有没有消息序号
			const msgRes = await httpRequest.Get('/lxy_contact/query_msg_record.action', params);
			console.log('msgRes', msgRes);
			if (msgRes.code === '0000') {
				let msg: Record<string, any> | null = null;
				if (msgRes.Records.length === 1) {
					msg = msgRes.Records[0];
				}
				console.log('ind', msg);
				if (msg) {
					if (msg.MsgClassify === '4') {
						msg.Sender = BASE_API.ENT_CODE + '-' + msg.Recver;
					}

					msg.Name = '微信用户';
					handleRecverMsg(msg);
				}
			}
		}
		function handleRecverMsg(msg: Record<string, any>) {
			let content = '';

			const newestInfo: Record<string, any> = {
				UserID: msg.Sender,
				time: formatDate(new Date(), 'HH:MM'),
				Msg: '',
				status: ENewestInfoStatus.unread,
				isWechat: true,
			};
			if (msg.Extend) {
				const arr = msg.Extend.split(',');
				const WechatIdStr = arr.find((a: string) => a.includes('WechatId'));
				if (WechatIdStr) {
					newestInfo.WechatId = WechatIdStr.split('=')[1];
				}
			}
			if (msg.Message && msg.ContentType === EMsgType.text) {
				// 本地保存聊天记录
				content = Base64.decode(msg.Message) || '';
				newestInfo.Msg = content;
			} else if (msg.Message && [EMsgType.img, EMsgType.file].includes(msg.ContentType)) {
				content = Base64.decode(msg.Message);
				newestInfo.Msg = msg.ContentType === EMsgType.img ? '[图片]' : '[文件]';
			}
			const chattingRecord: IChattingRecord = {
				name: msg.Name,
				time: formatDate(new Date(), 'YYYY-mm-dd HH:MM:SS'),
				content: content,
				identity: EIdentity.Customer,
				ContentType: msg.ContentType,
			};
			saveChattingRecord(chattingRecord, msg.Sender);
			saveNewestUserInfo(newestInfo);
		}
	});
})();

onMounted(() => {
	nextTick(() => {
		scrollToBottom();
	});
});
onUnmounted(() => {
	ws.closeWebSocket();
});
const scrollToBottom = () => {
	const chattingRecordEl = document.querySelector('.dialog-box');
	if (chattingRecordEl) {
		chattingRecordEl.scrollTop = chattingRecordEl.scrollHeight;
	}
};
</script>
<style lang="scss" scoped>
.container {
	display: flex;
	justify-content: center;
	align-items: center;
	height: calc(100vh - 120px);
}
.chat-box {
	width: 840px;
	display: flex;
	background-color: var(--next-color-white);
	box-shadow: var(--el-box-shadow-light);
	height: 554px;
	.user-list {
		width: 240px;
		height: 100%;
		border-right: 1px solid #e6e8eb;
		overflow-y: auto;
		background-color: var(--next-bg-main-color);
		transition: width 0.5s;
		.user-item {
			height: 50px;
			display: flex;
			align-items: center;
			cursor: pointer;
			background-color: #fff;
			&.active {
				background-color: #bbbbbb2b;
			}
			.el-image {
				width: 44px;
				height: 44px;
			}
			.info {
				flex: 1;
				margin-right: 10px;
				margin-left: 10px;

				.title {
					font-size: 15px;
					margin-bottom: 5px;
				}
				.the-latest-word {
					font-size: 12px;
					color: #909399;
				}
				.title,
				.the-latest-word {
					width: 114px;
					overflow: hidden;
					white-space: nowrap;
					text-overflow: ellipsis;
				}
			}
			.other {
				width: 40px;
				display: flex;
				flex-direction: column;
				align-items: center;
				margin-top: 10px;
				height: 100%;
				.the-latest-word-time {
					color: #909399;
				}
				.unread-num {
					width: 10px;
					height: 10px;
					background: red;
					color: #fff;
					border-radius: 50%;
					line-height: 18px;
					text-align: center;
				}
			}
		}
	}
	.left {
		min-width: 600px;
		flex: 1;
		border-right: 1px solid #e6e8eb;
		.head {
			display: flex;
			padding: 0px 10px;
			height: 44px;
			align-items: center;
			border-bottom: 1px solid #e6e8eb;
			.title-left {
				margin-left: 10px;
			}
		}
		.dialog-box {
			height: 404px;
		}
	}
	.right {
		display: flex;
		flex-direction: column;
		align-items: center;
		padding-top: 40px;
		width: 240px;
		transition: width 0.5s;
		img {
			width: 18px;
			margin-right: 10px;
		}
		.avatar {
			width: 70px;
		}
		.title {
			font-size: 18px;
			margin-bottom: 25px;
		}
		.address,
		.domain-name {
			display: flex;
			width: 100%;
			margin-left: 20px;
			margin-bottom: 15px;
		}
	}
	.handler {
		border-top: 1px solid #e6e8eb;
		padding: 15px 15px 8px 15px;
		position: relative;
		.emoji-content {
			position: absolute;
			display: none;
			left: 10px;
			top: -190px;
			width: 360px;
			height: 180px;
			background-color: var(--next-color-white);
			overflow-y: auto;
			font-size: 20px;
			box-shadow: var(--el-box-shadow-light);

			.emoji {
				display: inline-flex;
				justify-content: center;
				width: 34px;
				height: 34px;
				cursor: pointer;
			}
		}
		.input {
			height: 50px;

			overflow-y: auto;
		}
		.tool-bar {
			display: flex;
			justify-content: space-between;
			.tool {
				display: flex;
				align-items: flex-end;
				img {
					width: 22px;
					cursor: pointer;
				}
				img:nth-child(2) {
					margin: 0 10px;
				}
			}
		}
	}
}
.dialog-box {
	width: 100%;
	background-color: var(--next-color-white);
	padding: 20px 15px;
	overflow-y: auto;
}
.not-chat {
	text-align: center;
	color: #909399;
	font-size: 12px;
}
.communication-time-box {
	text-align: center;
}
.communication-time {
	display: inline-block;
	margin: 24px 12px 0;
	padding: 5px 12px;
	font-size: 12px;
	line-height: 18px;
	color: #606266;
	border-radius: 4px;
	background: #f5f7fa;
}
.chat-item {
	margin-bottom: 16px;
	.title {
		margin-bottom: 4px;
		font-size: 12px;
		line-height: 12px;
		color: #a4a0aa;
		min-width: 66px;
	}
	.content {
		font-size: 14px;
		word-break: break-all;
		border-radius: 4px;
		border-radius: 0 8px 8px 8px;
		background: #eff1f7;
		white-space: pre-line;
		line-height: 22px;
		padding: 12px;
		max-width: 80%;
		display: inline-block;
	}
	.file {
		display: flex;
		border: 1px solid #ebeef5;
		width: 298px;
		height: 65px;
		background: #fff;
		border-radius: 8px 0 8px 8px;
		padding: 12px 8px 12px 12px;
		cursor: pointer;
		.el-image {
			// margin: 12px 8px 12px 12px;
			margin-right: 10px;
		}
		.info {
			width: calc(100% - 55px);
			.title {
				color: #303133;
				text-align: left;
				overflow: hidden;
				white-space: nowrap;
				text-overflow: ellipsis;
				width: 100%;
				margin-top: 3px;
				margin-bottom: 8px;
			}
			span {
				color: #909399;
				font-weight: 400;
				&.size {
					margin-right: 10px;
				}
			}
		}
	}
}
.customer {
	display: flex;
	flex-direction: column;
	align-items: flex-end;

	.content {
		border-radius: 8px 0px 8px 8px;
	}
}
.retract-right {
	cursor: pointer;
}
</style>
